package com.demo.controller.admin;

import com.demo.dao.OrderDao;
import com.demo.dao.UserDao;
import com.demo.dao.VenueDao;
import com.demo.entity.Order;
import com.demo.entity.User;
import com.demo.entity.Venue;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
@Transactional
class AdminOrderControllerIT {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private VenueDao venueDao;

    private final int PAGE_SIZE = 10;
    private final int TOTAL_ORDERS = 207;
    private final int TOTAL_USERS = 5;
    private final int TOTAL_VENUES = 10;

    private int TOTAL_ORDERS_STATE1 = 0;
    private int TOTAL_ORDERS_STATE2 = 0;
    private int TOTAL_ORDERS_STATE3 = 0;

    private List<Integer> generatedOrderIds = new ArrayList<>();
    private List<Integer> generatedVenueIds = new ArrayList<>();

    @BeforeEach
    void setUp() {
        // 清空并初始化测试数据
        orderDao.deleteAll();
        userDao.deleteAll();
        venueDao.deleteAll();

        LocalDateTime baseTime = LocalDateTime.now();

        // 1. 插入用户测试数据
        IntStream.rangeClosed(1, TOTAL_USERS).forEach(i -> {
            User user = new User();
            user.setUserID("testUser" + i);
            user.setUserName("用户" + i);
            user.setPassword("password" + i);
            user.setEmail("user" + i + "@example.com");
            user.setPhone("1380013800" + i);
            user.setIsadmin(i == 1 ? 1 : 0); // 第一个用户是管理员
            user.setPicture("/images/avatar" + i + ".jpg");
            userDao.save(user);
        });

        // 2. 插入场馆测试数据
        IntStream.rangeClosed(1, TOTAL_VENUES).forEach(i -> {
            Venue venue = new Venue();
            // 不设置ID，让数据库自动生成
            venue.setVenueName("场馆" + i);
            venue.setAddress("地址" + i);
            venue.setOpen_time("08:00");
            venue.setClose_time("22:00");
            venue.setPrice(100);
            venue.setDescription("描述" + i);
            venue.setPicture("/images/venue" + i + ".jpg");
            Venue savedVenue = venueDao.save(venue);
            generatedVenueIds.add(savedVenue.getVenueID()); // 保存生成的ID
        });

        // 3. 插入订单测试数据（关联用户和场馆）
        IntStream.rangeClosed(1, TOTAL_ORDERS).forEach(i -> {
            String userID = "testUser" + ((i % TOTAL_USERS) + 1); // 循环分配用户
            int venueID = generatedVenueIds.get(i % TOTAL_VENUES); // 使用已保存的场馆ID
            Order order = new Order();
            order.setUserID(userID);
            order.setVenueID(venueID);
            order.setOrderTime(baseTime.minusDays(TOTAL_ORDERS - i));
            order.setStartTime(baseTime.minusDays(TOTAL_ORDERS - i).plusHours(2));
            order.setState(i % 3 + 1); // 状态1,2,3循环
            order.setHours(2);
            order.setTotal(200);
            
            switch (i%3 + 1){
                case 1:TOTAL_ORDERS_STATE1 ++;break;
                case 2:TOTAL_ORDERS_STATE2 ++;break;
                case 3:TOTAL_ORDERS_STATE3 ++;break;
                default:break;
            }
            orderDao.save(order);
        });

        // 添加验证
        long count = orderDao.count();
        for(Order o : orderDao.findAll()){
            generatedOrderIds.add(o.getOrderID());
        }
        System.out.println("Inserted orders count: " + count);
        assertTrue(count > 0, "测试数据未正确插入");
    }

    @Test
    void getOrderList_ShouldReturnPaginatedResults() throws Exception {
        mockMvc.perform(get("/admin/getOrderList.do").param("page", "1"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$").isArray())
                .andExpect(jsonPath("$.length()").value(PAGE_SIZE));
    }

    @Test
    void getOrderList_ShouldReturnPaginatedResultsLastPage() throws Exception {
        mockMvc.perform(get("/admin/getOrderList.do")
                        .param("page", String.valueOf(TOTAL_ORDERS_STATE1 / PAGE_SIZE + 1)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$").isArray())
                .andExpect(jsonPath("$.length()").value(TOTAL_ORDERS_STATE1 % PAGE_SIZE));
    }

    @Test
    void adminOperations_ShouldAllowDirectAccess() throws Exception {
        // 测试直接访问管理员操作
        mockMvc.perform(post("/passOrder.do")
                        .param("orderID", String.valueOf(generatedOrderIds.get(0))))
                .andExpect(status().isOk())
                .andExpect(content().string("true"));
    }

    @Test
    void orderResponse_ShouldContainBasicOrderInfo() throws Exception {
        // 验证返回的订单包含基本信息 (userID 和 venueName)
        mockMvc.perform(get("/admin/getOrderList.do"))
                .andExpect(jsonPath("$[0].userID").exists())
                .andExpect(jsonPath("$[0].venueName").exists());
    }

    @Test
    void passOrder_ShouldUpdateStateInDatabase() throws Exception {
        int orderId = generatedOrderIds.get(0);

        mockMvc.perform(post("/passOrder.do")
                        .param("orderID", String.valueOf(orderId)))
                .andExpect(status().isOk())
                .andExpect(content().string("true"));

        // 验证数据库状态
        Order updated = orderDao.findByOrderID(orderId);
        assertEquals(2, updated.getState()); // 2表示审核通过
    }

    @Test
    void rejectOrder_ShouldUpdateStateInDatabase() throws Exception {
        int orderId = generatedOrderIds.get(1);

        mockMvc.perform(post("/rejectOrder.do")
                        .param("orderID", String.valueOf(orderId)))
                .andExpect(status().isOk())
                .andExpect(content().string("true"));

        // 验证数据库状态
        Order updated = orderDao.findByOrderID(orderId);
        assertEquals(3, updated.getState()); // 3表示拒绝
    }

    @Test
    void reservationManage_ShouldCountPendingOrders() throws Exception {
        long pendingCount = orderDao.findAllByState(1, PageRequest.of(0, 1))
                .getTotalElements();

        mockMvc.perform(get("/reservation_manage"))
                .andExpect(status().isOk())
                .andExpect(model().attributeExists("total"))
                .andExpect(model().attribute("total", (int) Math.ceil((double) pendingCount / PAGE_SIZE)));
    }

    @Test
    void getOrderList_ShouldFilterByState() throws Exception {
        // 确保只返回state=1的待审核订单
        mockMvc.perform(get("/admin/getOrderList.do"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[?(@.state != 1)]").doesNotExist());
    }
} 